<!DOCTYPE html>
<html lang=zh>
<head>
  <meta charset="utf-8">
  
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
  <meta name="renderer" content="webkit">
  <meta http-equiv="Cache-Control" content="no-transform" />
  <meta http-equiv="Cache-Control" content="no-siteapp" />
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="format-detection" content="telephone=no,email=no,adress=no">
  <!-- Color theme for statusbar -->
  <meta name="theme-color" content="#000000" />
  <!-- 强制页面在当前窗口以独立页面显示,防止别人在框架里调用页面 -->
  <meta http-equiv="window-target" content="_top" />
  
  
  <title>个人吐血系列-总结Spring | Dreamcat</title>
  <meta name="description" content="个人感觉，Spring这一块，不仅会用，还得知道底层的源码或者是说初始化加载等过程吧，这篇就不介绍如何配置以及各个注解的使用，在这里不是重点。  大纲图 什么是Spring框架我们一般说 Spring 框架指的都是 Spring Framework，它是很多模块的集合，使用这些模块可以很方便地协助我们进行开发。这些模块是：核心容器、数据访问&#x2F;集成,、Web、AOP（面向切面编程）、工具、消息和测">
<meta property="og:type" content="article">
<meta property="og:title" content="个人吐血系列-总结Spring">
<meta property="og:url" content="http://dreamcat.ink/2020/03/29/ge-ren-tu-xie-xi-lie-zong-jie-spring/index.html">
<meta property="og:site_name" content="Dreamcat">
<meta property="og:description" content="个人感觉，Spring这一块，不仅会用，还得知道底层的源码或者是说初始化加载等过程吧，这篇就不介绍如何配置以及各个注解的使用，在这里不是重点。  大纲图 什么是Spring框架我们一般说 Spring 框架指的都是 Spring Framework，它是很多模块的集合，使用这些模块可以很方便地协助我们进行开发。这些模块是：核心容器、数据访问&#x2F;集成,、Web、AOP（面向切面编程）、工具、消息和测">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gitee.com/dreamcater/blog-img/raw/master/uPic/Spring%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98-F2ktkQ.png">
<meta property="og:image" content="http://media.dreamcat.ink//20200201150935.png">
<meta property="og:image" content="http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-17/5496407.jpg">
<meta property="og:image" content="http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-11/60679444.jpg">
<meta property="og:image" content="http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-11/49790288.jpg">
<meta property="og:image" content="http://media.dreamcat.ink//20200203211202.png">
<meta property="article:published_time" content="2020-03-29T07:45:57.000Z">
<meta property="article:modified_time" content="2020-10-30T12:58:56.448Z">
<meta property="article:author" content="买斯基">
<meta property="article:tag" content="spring">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/dreamcater/blog-img/raw/master/uPic/Spring%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98-F2ktkQ.png">
  <!-- Canonical links -->
  <link rel="canonical" href="http://dreamcat.ink/2020/03/29/ge-ren-tu-xie-xi-lie-zong-jie-spring/index.html">
  
    <link rel="alternate" href="/atom.xml" title="Dreamcat" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png" type="image/x-icon">
  
  
<link rel="stylesheet" href="/css/style.css">

  
  
  
  
<meta name="generator" content="Hexo 4.2.0"><link rel="stylesheet" href="/css/prism-tomorrow.css" type="text/css"></head>


<body class="main-center" itemscope itemtype="http://schema.org/WebPage">
  <header class="header" itemscope itemtype="http://schema.org/WPHeader">
  <div class="slimContent">
    <div class="navbar-header">
      
      
      <div class="profile-block text-center">
        <a id="avatar" href="https://github.com/DreamCats" target="_blank">
          <img class="img-circle img-rotate" src="/images/avatar.jpg" width="200" height="200">
        </a>
        <h2 id="name" class="hidden-xs hidden-sm">Dreamcat</h2>
        <h3 id="title" class="hidden-xs hidden-sm hidden-md">ドリームキャット</h3>
        <small id="location" class="text-muted hidden-xs hidden-sm"><i class="icon icon-map-marker"></i> Chengdu, China</small>
      </div>
      
      <div class="search" id="search-form-wrap">

    <form class="search-form sidebar-form">
        <div class="input-group">
            <input type="text" class="search-form-input form-control" placeholder="搜索" />
            <span class="input-group-btn">
                <button type="submit" class="search-form-submit btn btn-flat" onclick="return false;"><i class="icon icon-search"></i></button>
            </span>
        </div>
    </form>
    <div class="ins-search">
  <div class="ins-search-mask"></div>
  <div class="ins-search-container">
    <div class="ins-input-wrapper">
      <input type="text" class="ins-search-input" placeholder="想要查找什么..." x-webkit-speech />
      <button type="button" class="close ins-close ins-selectable" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
    </div>
    <div class="ins-section-wrapper">
      <div class="ins-section-container"></div>
    </div>
  </div>
</div>


</div>
      <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#main-navbar" aria-controls="main-navbar" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
    </div>
    <nav id="main-navbar" class="collapse navbar-collapse" itemscope itemtype="http://schema.org/SiteNavigationElement" role="navigation">
      <ul class="nav navbar-nav main-nav ">
        
        
        <li class="menu-item menu-item-home">
          <a href="/.">
            
            <i class="icon icon-home-fill"></i>
            
            <span class="menu-title">首页</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-archives">
          <a href="/archives">
            
            <i class="icon icon-archives-fill"></i>
            
            <span class="menu-title">归档</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-categories">
          <a href="/categories">
            
            <i class="icon icon-folder"></i>
            
            <span class="menu-title">分类</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-tags">
          <a href="/tags">
            
            <i class="icon icon-tags"></i>
            
            <span class="menu-title">标签</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-links">
          <a href="/links">
            
            <i class="icon icon-friendship"></i>
            
            <span class="menu-title">友链</span>
          </a>
        </li>
        
        
        <li class="menu-item menu-item-about">
          <a href="/about">
            
            <i class="icon icon-cup-fill"></i>
            
            <span class="menu-title">关于</span>
          </a>
        </li>
        
      </ul>
      
	
    <ul class="social-links">
    	
        <li><a href="https://github.com/DreamCats" target="_blank" title="Github" data-toggle=tooltip data-placement=top><i class="icon icon-github"></i></a></li>
        
        <li><a href="https://github.com/DreamCats" target="_blank" title="Weibo" data-toggle=tooltip data-placement=top><i class="icon icon-weibo"></i></a></li>
        
        <li><a href="https://github.com/DreamCats" target="_blank" title="Twitter" data-toggle=tooltip data-placement=top><i class="icon icon-twitter"></i></a></li>
        
        <li><a href="https://github.com/DreamCats" target="_blank" title="Behance" data-toggle=tooltip data-placement=top><i class="icon icon-behance"></i></a></li>
        
        <li><a href="/atom.xml" target="_blank" title="Rss" data-toggle=tooltip data-placement=top><i class="icon icon-rss"></i></a></li>
        
    </ul>

    </nav>
  </div>
</header>

  
    <aside class="sidebar" itemscope itemtype="http://schema.org/WPSideBar">
  <div class="slimContent">
    
      <div class="widget">
    <h3 class="widget-title">公告</h3>
    <div class="widget-body">
        <div id="board">
            <div class="content">
                <p>dream!</p>
            </div>
        </div>
    </div>
</div>

    
      
  <div class="widget">
    <h3 class="widget-title">分类</h3>
    <div class="widget-body">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/algorithm/">algorithm</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/db/">db</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/java/">java</a><span class="category-list-count">17</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/linux/">linux</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/spring/">spring</a><span class="category-list-count">9</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/vue/">vue</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/web/">web</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%B7%A5%E5%85%B7/">工具</a><span class="category-list-count">17</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E7%A7%8B%E6%8B%9B/">秋招</a><span class="category-list-count">11</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget">
    <h3 class="widget-title">标签</h3>
    <div class="widget-body">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/Dubbo/" rel="tag">Dubbo</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/MQ/" rel="tag">MQ</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/db/" rel="tag">db</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/dubbo/" rel="tag">dubbo</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/frp/" rel="tag">frp</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/github/" rel="tag">github</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/java/" rel="tag">java</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/java%E5%9F%BA%E7%A1%80/" rel="tag">java基础</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/java%E9%9B%86%E5%90%88/" rel="tag">java集合</a><span class="tag-list-count">11</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/jvm/" rel="tag">jvm</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/linux/" rel="tag">linux</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mongodb/" rel="tag">mongodb</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mybatis/" rel="tag">mybatis</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/nvm/" rel="tag">nvm</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/python/" rel="tag">python</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/redis/" rel="tag">redis</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/spring/" rel="tag">spring</a><span class="tag-list-count">9</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ubuntu/" rel="tag">ubuntu</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/vscode/" rel="tag">vscode</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/vue/" rel="tag">vue</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/web/" rel="tag">web</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" rel="tag">多线程</a><span class="tag-list-count">7</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E7%AE%97%E6%B3%95/" rel="tag">算法</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E7%BB%88%E7%AB%AF/" rel="tag">终端</a><span class="tag-list-count">2</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E8%99%9A%E6%8B%9F%E6%9C%BA/" rel="tag">虚拟机</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/" rel="tag">计算机网络</a><span class="tag-list-count">1</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget">
    <h3 class="widget-title">标签云</h3>
    <div class="widget-body tagcloud">
      <a href="/tags/Dubbo/" style="font-size: 13px;">Dubbo</a> <a href="/tags/MQ/" style="font-size: 13.2px;">MQ</a> <a href="/tags/db/" style="font-size: 13.4px;">db</a> <a href="/tags/dubbo/" style="font-size: 13px;">dubbo</a> <a href="/tags/frp/" style="font-size: 13px;">frp</a> <a href="/tags/github/" style="font-size: 13.4px;">github</a> <a href="/tags/java/" style="font-size: 13px;">java</a> <a href="/tags/java%E5%9F%BA%E7%A1%80/" style="font-size: 13.2px;">java基础</a> <a href="/tags/java%E9%9B%86%E5%90%88/" style="font-size: 14px;">java集合</a> <a href="/tags/jvm/" style="font-size: 13px;">jvm</a> <a href="/tags/linux/" style="font-size: 13px;">linux</a> <a href="/tags/mongodb/" style="font-size: 13px;">mongodb</a> <a href="/tags/mybatis/" style="font-size: 13.2px;">mybatis</a> <a href="/tags/nvm/" style="font-size: 13px;">nvm</a> <a href="/tags/python/" style="font-size: 13px;">python</a> <a href="/tags/redis/" style="font-size: 13.2px;">redis</a> <a href="/tags/spring/" style="font-size: 13.8px;">spring</a> <a href="/tags/ubuntu/" style="font-size: 13px;">ubuntu</a> <a href="/tags/vscode/" style="font-size: 13px;">vscode</a> <a href="/tags/vue/" style="font-size: 13.4px;">vue</a> <a href="/tags/web/" style="font-size: 13px;">web</a> <a href="/tags/%E5%A4%9A%E7%BA%BF%E7%A8%8B/" style="font-size: 13.6px;">多线程</a> <a href="/tags/%E7%AE%97%E6%B3%95/" style="font-size: 13px;">算法</a> <a href="/tags/%E7%BB%88%E7%AB%AF/" style="font-size: 13.2px;">终端</a> <a href="/tags/%E8%99%9A%E6%8B%9F%E6%9C%BA/" style="font-size: 13px;">虚拟机</a> <a href="/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/" style="font-size: 13px;">计算机网络</a>
    </div>
  </div>

    
      
  <div class="widget">
    <h3 class="widget-title">归档</h3>
    <div class="widget-body">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/04/">四月 2020</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/03/">三月 2020</a><span class="archive-list-count">8</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/02/">二月 2020</a><span class="archive-list-count">6</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/01/">一月 2020</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/12/">十二月 2019</a><span class="archive-list-count">3</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/11/">十一月 2019</a><span class="archive-list-count">5</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/10/">十月 2019</a><span class="archive-list-count">8</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/09/">九月 2019</a><span class="archive-list-count">5</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/08/">八月 2019</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/07/">七月 2019</a><span class="archive-list-count">7</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/06/">六月 2019</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/05/">五月 2019</a><span class="archive-list-count">9</span></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/03/">三月 2019</a><span class="archive-list-count">1</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget">
    <h3 class="widget-title">最新文章</h3>
    <div class="widget-body">
      <ul class="recent-post-list list-unstyled no-thumbnail">
        
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/categories/%E7%A7%8B%E6%8B%9B/">秋招</a>
              </p>
              <p class="item-title">
                <a href="/2020/04/02/ge-ren-tu-xie-xi-lie-zong-jie-ji-suan-ji-wang-luo/" class="title">个人吐血系列-总结计算机网络</a>
              </p>
              <p class="item-date">
                <time datetime="2020-04-01T17:42:22.000Z" itemprop="datePublished">2020-04-02</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/categories/%E7%A7%8B%E6%8B%9B/">秋招</a>
              </p>
              <p class="item-title">
                <a href="/2020/04/01/ge-ren-tu-xie-xi-lie-zong-jie-rocketmq/" class="title">个人吐血系列-总结RocketMQ</a>
              </p>
              <p class="item-date">
                <time datetime="2020-04-01T04:42:56.000Z" itemprop="datePublished">2020-04-01</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/categories/%E7%A7%8B%E6%8B%9B/">秋招</a>
              </p>
              <p class="item-title">
                <a href="/2020/04/01/ge-ren-tu-xie-xi-lie-zong-jie-dubbo/" class="title">个人吐血系列-总结Dubbo</a>
              </p>
              <p class="item-date">
                <time datetime="2020-03-31T16:04:46.000Z" itemprop="datePublished">2020-04-01</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/categories/%E7%A7%8B%E6%8B%9B/">秋招</a>
              </p>
              <p class="item-title">
                <a href="/2020/03/31/ge-ren-tu-xie-xi-lie-zong-jie-redis/" class="title">个人吐血系列-总结Redis</a>
              </p>
              <p class="item-date">
                <time datetime="2020-03-31T13:59:25.000Z" itemprop="datePublished">2020-03-31</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/categories/%E7%A7%8B%E6%8B%9B/">秋招</a>
              </p>
              <p class="item-title">
                <a href="/2020/03/30/ge-ren-tu-xie-xi-lie-zong-jie-mysql/" class="title">个人吐血系列-总结Mysql</a>
              </p>
              <p class="item-date">
                <time datetime="2020-03-30T07:13:08.000Z" itemprop="datePublished">2020-03-30</time>
              </p>
            </div>
          </li>
          
      </ul>
    </div>
  </div>
  

    
  </div>
</aside>

  
  
<aside class="sidebar sidebar-toc collapse" id="collapseToc" itemscope itemtype="http://schema.org/WPSideBar">
  <div class="slimContent">
    <nav id="toc" class="article-toc">
      <h3 class="toc-title">文章目录</h3>
      <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#大纲图"><span class="toc-number">1.</span> <span class="toc-text">大纲图</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#什么是Spring框架"><span class="toc-number">1.1.</span> <span class="toc-text">什么是Spring框架</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#列举一些重要的Spring模块"><span class="toc-number">1.2.</span> <span class="toc-text">列举一些重要的Spring模块</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#RestController-VS-Controller"><span class="toc-number">1.3.</span> <span class="toc-text">@RestController VS Controller</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#Controller"><span class="toc-number">1.3.1.</span> <span class="toc-text">Controller</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#RestController"><span class="toc-number">1.3.2.</span> <span class="toc-text">RestController</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#谈谈SpringIOC和AOP"><span class="toc-number">1.4.</span> <span class="toc-text">谈谈SpringIOC和AOP</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#IOC"><span class="toc-number">1.4.1.</span> <span class="toc-text">IOC</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#ioc容器初始化流程"><span class="toc-number">1.4.1.1.</span> <span class="toc-text">ioc容器初始化流程</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#大概总结一下"><span class="toc-number">1.4.1.2.</span> <span class="toc-text">大概总结一下</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#AOP"><span class="toc-number">1.4.2.</span> <span class="toc-text">AOP</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#Spring-AOP-和-AspectJ-AOP-有什么区别"><span class="toc-number">1.4.2.1.</span> <span class="toc-text">Spring AOP 和 AspectJ AOP 有什么区别</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#源码总结"><span class="toc-number">1.4.2.2.</span> <span class="toc-text">源码总结</span></a></li></ol></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Spring-Bean"><span class="toc-number">1.5.</span> <span class="toc-text">Spring Bean</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#作用域"><span class="toc-number">1.5.1.</span> <span class="toc-text">作用域</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Spring的单例有线程安全问题吗"><span class="toc-number">1.5.2.</span> <span class="toc-text">Spring的单例有线程安全问题吗</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Component和Bean的区别"><span class="toc-number">1.5.3.</span> <span class="toc-text">Component和Bean的区别</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#将类声明为bean有哪些"><span class="toc-number">1.5.4.</span> <span class="toc-text">将类声明为bean有哪些</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#Bean的声明周期"><span class="toc-number">1.5.5.</span> <span class="toc-text">Bean的声明周期</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#SpringMVC"><span class="toc-number">1.6.</span> <span class="toc-text">SpringMVC</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#工作原理"><span class="toc-number">1.6.1.</span> <span class="toc-text">工作原理</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Spring都用到了哪些设计模式"><span class="toc-number">1.7.</span> <span class="toc-text">Spring都用到了哪些设计模式</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Spring事务"><span class="toc-number">1.8.</span> <span class="toc-text">Spring事务</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#管理事物有几种"><span class="toc-number">1.8.1.</span> <span class="toc-text">管理事物有几种</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#隔离级别"><span class="toc-number">1.8.2.</span> <span class="toc-text">隔离级别</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#源码分析"><span class="toc-number">1.8.3.</span> <span class="toc-text">源码分析</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Springboot启动流程"><span class="toc-number">1.9.</span> <span class="toc-text">Springboot启动流程</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#SpringApplication实例"><span class="toc-number">1.9.1.</span> <span class="toc-text">SpringApplication实例</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ConfigurableApplicationContext的run方法"><span class="toc-number">1.9.2.</span> <span class="toc-text">ConfigurableApplicationContext的run方法</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#refreshContext"><span class="toc-number">1.9.3.</span> <span class="toc-text">refreshContext()</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ServletWebServerApplicationContext"><span class="toc-number">1.9.4.</span> <span class="toc-text">ServletWebServerApplicationContext</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#SpringBootApplication的注解"><span class="toc-number">1.9.5.</span> <span class="toc-text">SpringBootApplication的注解</span></a></li></ol></li></ol></li></ol>
    </nav>
  </div>
</aside>

<main class="main" role="main">
  <div class="content">
  <article id="post-个人吐血系列-总结Spring" class="article article-type-post" itemscope itemtype="http://schema.org/BlogPosting">
    
    <div class="article-header">
      
        
  
    <h1 class="article-title" itemprop="name">
      个人吐血系列-总结Spring
    </h1>
  

      
      <div class="article-meta">
        <span class="article-date">
    <i class="icon icon-calendar-check"></i>
	<a href="/2020/03/29/ge-ren-tu-xie-xi-lie-zong-jie-spring/" class="article-date">
	  <time datetime="2020-03-29T07:45:57.000Z" itemprop="datePublished">2020-03-29</time>
	</a>
</span>
        
  <span class="article-category">
    <i class="icon icon-folder"></i>
    <a class="article-category-link" href="/categories/%E7%A7%8B%E6%8B%9B/">秋招</a>
  </span>

        
  <span class="article-tag">
    <i class="icon icon-tags"></i>
	<a class="article-tag-link" href="/tags/spring/" rel="tag">spring</a>
  </span>


        

        <span class="post-comment"><i class="icon icon-comment"></i> <a href="/2020/03/29/ge-ren-tu-xie-xi-lie-zong-jie-spring/#comments" class="article-comment-link">评论</a></span>
        
	
		<span class="post-wordcount hidden-xs" itemprop="wordCount">字数统计: 5.1k(字)</span>
	
	
		<span class="post-readcount hidden-xs" itemprop="timeRequired">阅读时长: 19(分)</span>
	

      </div>
    </div>
    <div class="article-entry marked-body" itemprop="articleBody">
      
        <blockquote>
<p>个人感觉，Spring这一块，不仅会用，还得知道底层的源码或者是说初始化加载等过程吧，这篇就不介绍如何配置以及各个注解的使用，在这里不是重点。</p>
</blockquote>
<h2 id="大纲图"><a href="#大纲图" class="headerlink" title="大纲图"></a>大纲图</h2><p><img src="https://gitee.com/dreamcater/blog-img/raw/master/uPic/Spring%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98-F2ktkQ.png" alt="Spring常见问题-F2ktkQ"></p>
<h3 id="什么是Spring框架"><a href="#什么是Spring框架" class="headerlink" title="什么是Spring框架"></a>什么是Spring框架</h3><p>我们一般说 Spring 框架指的都是 Spring Framework，它是很多模块的集合，使用这些模块可以很方便地协助我们进行开发。这些模块是：核心容器、数据访问/集成,、Web、AOP（面向切面编程）、工具、消息和测试模块。比如：Core Container 中的 Core 组件是Spring 所有组件的核心，Beans 组件和 Context 组件是实现IOC和依赖注入的基础，AOP组件用来实现面向切面编程。</p>
<p>Spring 官网列出的 Spring 的 6 个特征:</p>
<ul>
<li><strong>核心技术</strong> ：依赖注入(DI)，AOP，事件(events)，资源，i18n，验证，数据绑定，类型转换，SpEL。</li>
<li><strong>测试</strong> ：模拟对象，TestContext框架，Spring MVC 测试，WebTestClient。</li>
<li><strong>数据访问</strong> ：事务，DAO支持，JDBC，ORM，编组XML。</li>
<li><strong>Web支持</strong> : Spring MVC和Spring WebFlux Web框架。</li>
<li><strong>集成</strong> ：远程处理，JMS，JCA，JMX，电子邮件，任务，调度，缓存。</li>
<li><strong>语言</strong> ：Kotlin，Groovy，动态语言。</li>
</ul>
<h3 id="列举一些重要的Spring模块"><a href="#列举一些重要的Spring模块" class="headerlink" title="列举一些重要的Spring模块"></a>列举一些重要的Spring模块</h3><ul>
<li><strong>Spring Core：</strong> 基础,可以说 Spring 其他所有的功能都需要依赖于该类库。主要提供 IoC 依赖注入功能。</li>
<li><strong>Spring Aspects</strong> ： 该模块为与AspectJ的集成提供支持。</li>
<li><strong>Spring AOP</strong> ：提供了面向切面的编程实现。</li>
<li><strong>Spring JDBC</strong> : Java数据库连接。</li>
<li><strong>Spring JMS</strong> ：Java消息服务。</li>
<li><strong>Spring ORM</strong> : 用于支持Hibernate等ORM工具。</li>
<li><strong>Spring Web</strong> : 为创建Web应用程序提供支持。</li>
<li><strong>Spring Test</strong> : 提供了对 JUnit 和 TestNG 测试的支持。</li>
</ul>
<h3 id="RestController-VS-Controller"><a href="#RestController-VS-Controller" class="headerlink" title="@RestController VS Controller"></a>@RestController VS Controller</h3><h4 id="Controller"><a href="#Controller" class="headerlink" title="Controller"></a>Controller</h4><p><strong><code>Controller</code> 返回一个页面</strong></p>
<p>单独使用 <code>@Controller</code> 不加 <code>@ResponseBody</code>的话一般使用在要返回一个视图的情况，这种情况属于比较传统的Spring MVC 的应用，对应于前后端不分离的情况。</p>
<h4 id="RestController"><a href="#RestController" class="headerlink" title="RestController"></a>RestController</h4><p><strong><code>@RestController</code> 返回JSON 或 XML 形式数据</strong></p>
<p>但<code>@RestController</code>只返回对象，对象数据直接以 JSON 或 XML 形式写入 HTTP 响应(Response)中，这种情况属于 RESTful Web服务，这也是目前日常开发所接触的最常用的情况（前后端分离）。</p>
<p><strong><code>@Controller +@ResponseBody</code> 返回JSON 或 XML 形式数据</strong></p>
<p>如果你需要在Spring4之前开发 RESTful Web服务的话，你需要使用<code>@Controller</code> 并结合<code>@ResponseBody</code>注解，也就是说<code>@Controller</code> +<code>@ResponseBody</code>= <code>@RestController</code>（Spring 4 之后新加的注解）。</p>
<h3 id="谈谈SpringIOC和AOP"><a href="#谈谈SpringIOC和AOP" class="headerlink" title="谈谈SpringIOC和AOP"></a>谈谈SpringIOC和AOP</h3><h4 id="IOC"><a href="#IOC" class="headerlink" title="IOC"></a>IOC</h4><p>IoC（Inverse of Control:控制反转）是一种<strong>设计思想</strong>，就是 <strong>将原本在程序中手动创建对象的控制权，交由Spring框架来管理。</strong> IoC 在其他语言中也有应用，并非 Spring 特有。 <strong>IoC 容器是 Spring 用来实现 IoC 的载体， IoC 容器实际上就是个Map（key，value）,Map 中存放的是各种对象。</strong></p>
<p>将对象之间的相互依赖关系交给 IoC 容器来管理，并由 IoC 容器完成对象的注入。这样可以很大程度上简化应用的开发，把应用从复杂的依赖关系中解放出来。 <strong>IoC 容器就像是一个工厂一样，当我们需要创建一个对象的时候，只需要配置好配置文件/注解即可，完全不用考虑对象是如何被创建出来的。</strong> 在实际项目中一个 Service 类可能有几百甚至上千个类作为它的底层，假如我们需要实例化这个 Service，你可能要每次都要搞清这个 Service 所有底层类的构造函数，这可能会把人逼疯。如果利用 IoC 的话，你只需要配置好，然后在需要的地方引用就行了，这大大增加了项目的可维护性且降低了开发难度。</p>
<p>Spring 时代我们一般通过 XML 文件来配置 Bean，后来开发人员觉得 XML 文件来配置不太好，于是 SpringBoot 注解配置就慢慢开始流行起来。</p>
<p>推荐阅读：<a href="https://www.zhihu.com/question/23277575/answer/169698662" target="_blank" rel="noopener">https://www.zhihu.com/question/23277575/answer/169698662</a></p>
<h5 id="ioc容器初始化流程"><a href="#ioc容器初始化流程" class="headerlink" title="ioc容器初始化流程"></a>ioc容器初始化流程</h5><p><strong>可以看到有很多PostProcessors的后置处理器</strong></p>
<pre class=" language-java"><code class="language-java"><span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">refresh</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">throws</span> BeansException<span class="token punctuation">,</span> IllegalStateException <span class="token punctuation">{</span>
   <span class="token comment" spellcheck="true">// 来个锁，不然 refresh() 还没结束，你又来个启动或销毁容器的操作，那不就乱套了嘛</span>
   <span class="token keyword">synchronized</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>startupShutdownMonitor<span class="token punctuation">)</span> <span class="token punctuation">{</span>

      <span class="token comment" spellcheck="true">// 准备工作，记录下容器的启动时间、标记“已启动”状态、处理配置文件中的占位符</span>
      <span class="token function">prepareRefresh</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

      <span class="token comment" spellcheck="true">// 这步比较关键，这步完成后，配置文件就会解析成一个个 Bean 定义，注册到 BeanFactory 中，</span>
      <span class="token comment" spellcheck="true">// 当然，这里说的 Bean 还没有初始化，只是配置信息都提取出来了，</span>
      <span class="token comment" spellcheck="true">// 注册也只是将这些信息都保存到了注册中心(说到底核心是一个 beanName-> beanDefinition 的 map)</span>
      ConfigurableListableBeanFactory beanFactory <span class="token operator">=</span> <span class="token function">obtainFreshBeanFactory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

      <span class="token comment" spellcheck="true">// 设置 BeanFactory 的类加载器，添加几个 BeanPostProcessor，手动注册几个特殊的 bean</span>
      <span class="token comment" spellcheck="true">// 这块待会会展开说</span>
      <span class="token function">prepareBeanFactory</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>

      <span class="token keyword">try</span> <span class="token punctuation">{</span>
         <span class="token comment" spellcheck="true">// 【这里需要知道 BeanFactoryPostProcessor 这个知识点，Bean 如果实现了此接口，</span>
         <span class="token comment" spellcheck="true">// 那么在容器初始化以后，Spring 会负责调用里面的 postProcessBeanFactory 方法。】</span>

         <span class="token comment" spellcheck="true">// 这里是提供给子类的扩展点，到这里的时候，所有的 Bean 都加载、注册完成了，但是都还没有初始化</span>
         <span class="token comment" spellcheck="true">// 具体的子类可以在这步的时候添加一些特殊的 BeanFactoryPostProcessor 的实现类或做点什么事</span>
         <span class="token function">postProcessBeanFactory</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>
         <span class="token comment" spellcheck="true">// 调用 BeanFactoryPostProcessor 各个实现类的 postProcessBeanFactory(factory) 方法</span>
         <span class="token function">invokeBeanFactoryPostProcessors</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>

         <span class="token comment" spellcheck="true">// 注册 BeanPostProcessor 的实现类，注意看和 BeanFactoryPostProcessor 的区别</span>
         <span class="token comment" spellcheck="true">// 此接口两个方法: postProcessBeforeInitialization 和 postProcessAfterInitialization</span>
         <span class="token comment" spellcheck="true">// 两个方法分别在 Bean 初始化之前和初始化之后得到执行。注意，到这里 Bean 还没初始化</span>
         <span class="token function">registerBeanPostProcessors</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>

         <span class="token comment" spellcheck="true">// 初始化当前 ApplicationContext 的 MessageSource，国际化这里就不展开说了，不然没完没了了</span>
         <span class="token function">initMessageSource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

         <span class="token comment" spellcheck="true">// 初始化当前 ApplicationContext 的事件广播器，这里也不展开了</span>
         <span class="token function">initApplicationEventMulticaster</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

         <span class="token comment" spellcheck="true">// 从方法名就可以知道，典型的模板方法(钩子方法)，</span>
         <span class="token comment" spellcheck="true">// 具体的子类可以在这里初始化一些特殊的 Bean（在初始化 singleton beans 之前）</span>
         <span class="token function">onRefresh</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

         <span class="token comment" spellcheck="true">// 注册事件监听器，监听器需要实现 ApplicationListener 接口。这也不是我们的重点，过</span>
         <span class="token function">registerListeners</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

         <span class="token comment" spellcheck="true">// 重点，重点，重点</span>
         <span class="token comment" spellcheck="true">// 初始化所有的 singleton beans</span>
         <span class="token comment" spellcheck="true">//（lazy-init 的除外）</span>
         <span class="token function">finishBeanFactoryInitialization</span><span class="token punctuation">(</span>beanFactory<span class="token punctuation">)</span><span class="token punctuation">;</span>

         <span class="token comment" spellcheck="true">// 最后，广播事件，ApplicationContext 初始化完成</span>
         <span class="token function">finishRefresh</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>

      <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">BeansException</span> ex<span class="token punctuation">)</span> <span class="token punctuation">{</span>
         <span class="token keyword">if</span> <span class="token punctuation">(</span>logger<span class="token punctuation">.</span><span class="token function">isWarnEnabled</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            logger<span class="token punctuation">.</span><span class="token function">warn</span><span class="token punctuation">(</span><span class="token string">"Exception encountered during context initialization - "</span> <span class="token operator">+</span>
                  <span class="token string">"cancelling refresh attempt: "</span> <span class="token operator">+</span> ex<span class="token punctuation">)</span><span class="token punctuation">;</span>
         <span class="token punctuation">}</span>

         <span class="token comment" spellcheck="true">// Destroy already created singletons to avoid dangling resources.</span>
         <span class="token comment" spellcheck="true">// 销毁已经初始化的 singleton 的 Beans，以免有些 bean 会一直占用资源</span>
         <span class="token function">destroyBeans</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

         <span class="token comment" spellcheck="true">// Reset 'active' flag.</span>
         <span class="token function">cancelRefresh</span><span class="token punctuation">(</span>ex<span class="token punctuation">)</span><span class="token punctuation">;</span>

         <span class="token comment" spellcheck="true">// 把异常往外抛</span>
         <span class="token keyword">throw</span> ex<span class="token punctuation">;</span>
      <span class="token punctuation">}</span>

      <span class="token keyword">finally</span> <span class="token punctuation">{</span>
         <span class="token comment" spellcheck="true">// Reset common introspection caches in Spring's core, since we</span>
         <span class="token comment" spellcheck="true">// might not ever need metadata for singleton beans anymore...</span>
         <span class="token function">resetCommonCaches</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
   <span class="token punctuation">}</span>
<span class="token punctuation">}</span></code></pre>
<h5 id="大概总结一下"><a href="#大概总结一下" class="headerlink" title="大概总结一下"></a>大概总结一下</h5><ol>
<li>Spring容器在启动的时候，先会保存所有注册进来的Bean的定义信息；<ol>
<li>xml注册bean；<bean></li>
<li>注解注册Bean；@Service、@Component、@Bean、xxx</li>
<li>Spring容器会合适的时机创建这些Bean<ol>
<li>用到这个bean的时候；利用getBean创建bean；创建好以后保存在容器中；</li>
<li>统一创建剩下所有的bean的时候；finishBeanFactoryInitialization()；</li>
</ol>
</li>
<li>后置处理器；BeanPostProcessor<ol>
<li>每一个bean创建完成，都会使用各种后置处理器进行处理；来增强bean的功能；比如<ol>
<li>AutowiredAnnotationBeanPostProcessor:处理自动注入</li>
<li>AnnotationAwareAspectJAutoProxyCreator:来做AOP功能；</li>
<li>xxx</li>
</ol>
</li>
</ol>
</li>
<li>事件驱动模型；<ol>
<li>ApplicationListener；事件监听；</li>
<li>ApplicationEventMulticaster；事件派发：</li>
</ol>
</li>
</ol>
</li>
</ol>
<p>更详细的源码可看</p>
<ol>
<li><a href="http://dreamcat.ink/2020/01/31/spring-springaop-yuan-ma-fen-xi/">http://dreamcat.ink/2020/01/31/spring-springaop-yuan-ma-fen-xi/ </a></li>
<li><a href="https://javadoop.com/post/spring-ioc]" target="_blank" rel="noopener"> https://javadoop.com/post/spring-ioc</a></li>
</ol>
<h4 id="AOP"><a href="#AOP" class="headerlink" title="AOP"></a>AOP</h4><p>AOP(Aspect-Oriented Programming:面向切面编程)能够将那些与业务无关，<strong>却为业务模块所共同调用的逻辑或责任（例如事务处理、日志管理、权限控制等）封装起来</strong>，便于<strong>减少系统的重复代码</strong>，<strong>降低模块间的耦合度</strong>，并<strong>有利于未来的可拓展性和可维护性</strong>。<br><strong>Spring AOP就是基于动态代理的</strong>，如果要代理的对象，实现了某个接口，那么Spring AOP会使用<strong>JDK Proxy</strong>，去创建代理对象，而对于没有实现接口的对象，就无法使用 JDK Proxy 去进行代理了，这时候Spring AOP会使用<strong>Cglib</strong> ，这时候Spring AOP会使用 <strong>Cglib</strong> 生成一个被代理对象的子类来作为代理。<br>当然你也可以使用 AspectJ ,Spring AOP 已经集成了AspectJ ，AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。<br>使用 AOP 之后我们可以把一些通用功能抽象出来，在需要用到的地方直接使用即可，这样大大简化了代码量。我们需要增加新功能时也方便，这样也提高了系统扩展性。日志功能、事务管理等等场景都用到了 AOP 。</p>
<h5 id="Spring-AOP-和-AspectJ-AOP-有什么区别"><a href="#Spring-AOP-和-AspectJ-AOP-有什么区别" class="headerlink" title="Spring AOP 和 AspectJ AOP 有什么区别"></a>Spring AOP 和 AspectJ AOP 有什么区别</h5><p><strong>Spring AOP 属于运行时增强，而 AspectJ 是编译时增强。</strong> Spring AOP 基于代理(Proxying)，而 AspectJ 基于字节码操作(Bytecode Manipulation)<br>Spring AOP 已经集成了 AspectJ ，AspectJ 应该算的上是 Java 生态系统中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加强大，但是 Spring AOP 相对来说更简单，<br>如果我们的切面比较少，那么两者性能差异不大。但是，当切面太多的话，最好选择 AspectJ ，它比Spring AOP 快很多。</p>
<h5 id="源码总结"><a href="#源码总结" class="headerlink" title="源码总结"></a>源码总结</h5><p><img src="http://media.dreamcat.ink//20200201150935.png" alt="AnnotationAwareAspectJAutoProxyCreator"></p>
<ol>
<li>@EnableAspectJAutoProxy 开启AOP功能</li>
<li>@EnableAspectJAutoProxy 会给容器中注册一个组件 AnnotationAwareAspectJAutoProxyCreator</li>
<li>AnnotationAwareAspectJAutoProxyCreator是一个后置处理器；</li>
<li>容器的创建流程：<ol>
<li>registerBeanPostProcessors（）注册后置处理器；创建AnnotationAwareAspectJAutoProxyCreator对象（<strong>Spring源码</strong>）</li>
<li>finishBeanFactoryInitialization（）初始化剩下的单实例bean（<strong>Spring源码</strong>）<ol>
<li>创建业务逻辑组件和切面组件</li>
<li>AnnotationAwareAspectJAutoProxyCreator拦截组件的创建过程</li>
<li>组件创建完之后，判断组件是否需要增强；是-&gt;切面的通知方法，包装成增强器（Advisor）;给业务逻辑组件创建一个代理对象（cglib）；</li>
</ol>
</li>
</ol>
</li>
<li>执行目标方法：<ol>
<li>代理对象执行目标方法</li>
<li>CglibAopProxy.intercept()；<ol>
<li>得到目标方法的拦截器链（增强器包装成拦截器MethodInterceptor）</li>
<li>利用拦截器的链式机制，依次进入每一个拦截器进行执行；</li>
<li>效果：<ol>
<li>正常执行：前置通知-》目标方法-》后置通知-》返回通知</li>
<li>出现异常：前置通知-》目标方法-》后置通知-》异常通知</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
</ol>
<h3 id="Spring-Bean"><a href="#Spring-Bean" class="headerlink" title="Spring Bean"></a>Spring Bean</h3><h4 id="作用域"><a href="#作用域" class="headerlink" title="作用域"></a>作用域</h4><ul>
<li>singleton : 唯一 bean 实例，Spring 中的 bean 默认都是单例的。</li>
<li>prototype : 每次请求都会创建一个新的 bean 实例。</li>
<li>request : 每一次HTTP请求都会产生一个新的bean，该bean仅在当前HTTP request内有效。</li>
<li>session : 每一次HTTP请求都会产生一个新的 bean，该bean仅在当前 HTTP session 内有效。</li>
<li>global-session： 全局session作用域，仅仅在基于portlet的web应用中才有意义，Spring5已经没有了。Portlet是能够生成语义代码(例如：HTML)片段的小型Java Web插件。它们基于portlet容器，可以像servlet一样处理HTTP请求。但是，与 servlet 不同，每个 portlet 都有不同的会话</li>
</ul>
<h4 id="Spring的单例有线程安全问题吗"><a href="#Spring的单例有线程安全问题吗" class="headerlink" title="Spring的单例有线程安全问题吗"></a>Spring的单例有线程安全问题吗</h4><p>大部分时候我们并没有在系统中使用多线程，所以很少有人会关注这个问题。单例 bean 存在线程问题，主要是因为当多个线程操作同一个对象的时候，对这个对象的非静态成员变量的写操作会存在线程安全问题。</p>
<p>常见的有两种解决办法：</p>
<ol>
<li>在Bean对象中尽量避免定义可变的成员变量（不太现实）。</li>
<li>在类中定义一个ThreadLocal成员变量，将需要的可变成员变量保存在 ThreadLocal 中（推荐的一种方式）。</li>
</ol>
<h4 id="Component和Bean的区别"><a href="#Component和Bean的区别" class="headerlink" title="Component和Bean的区别"></a>Component和Bean的区别</h4><ol>
<li>作用对象不同: <code>@Component</code> 注解作用于类，而<code>@Bean</code>注解作用于方法。</li>
<li><code>@Component</code>通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中（我们可以使用 <code>@ComponentScan</code> 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中）。<code>@Bean</code> 注解通常是我们在标有该注解的方法中定义产生这个 bean,<code>@Bean</code>告诉了Spring这是某个类的示例，当我需要用它的时候还给我。</li>
<li><code>@Bean</code> 注解比 <code>Component</code> 注解的自定义性更强，而且很多地方我们只能通过 <code>@Bean</code> 注解来注册bean。比如当我们引用第三方库中的类需要装配到 <code>Spring</code>容器时，则只能通过 <code>@Bean</code>来实现。</li>
</ol>
<h4 id="将类声明为bean有哪些"><a href="#将类声明为bean有哪些" class="headerlink" title="将类声明为bean有哪些"></a>将类声明为bean有哪些</h4><p>我们一般使用 <code>@Autowired</code> 注解自动装配 bean，要想把类标识成可用于 <code>@Autowired</code> 注解自动装配的 bean 的类,采用以下注解可实现：</p>
<ul>
<li><code>@Component</code> ：通用的注解，可标注任意类为 <code>Spring</code> 组件。如果一个Bean不知道属于哪个层，可以使用<code>@Component</code> 注解标注。</li>
<li><code>@Repository</code> : 对应持久层即 Dao 层，主要用于数据库相关操作。</li>
<li><code>@Service</code> : 对应服务层，主要涉及一些复杂的逻辑，需要用到 Dao层。</li>
<li><code>@Controller</code> : 对应 Spring MVC 控制层，主要用户接受用户请求并调用 Service 层返回数据给前端页面。</li>
</ul>
<h4 id="Bean的声明周期"><a href="#Bean的声明周期" class="headerlink" title="Bean的声明周期"></a>Bean的声明周期</h4><p><img src="http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-9-17/5496407.jpg" alt="bean周期"></p>
<ul>
<li>Bean 容器找到配置文件中 Spring Bean 的定义。</li>
<li>Bean 容器利用 Java Reflection API 创建一个Bean的实例。</li>
<li>如果涉及到一些属性值 利用 <code>set()</code>方法设置一些属性值。</li>
<li>如果 Bean 实现了 <code>BeanNameAware</code> 接口，调用 <code>setBeanName()</code>方法，传入Bean的名字。</li>
<li>如果 Bean 实现了 <code>BeanClassLoaderAware</code> 接口，调用 <code>setBeanClassLoader()</code>方法，传入 <code>ClassLoader</code>对象的实例。</li>
<li>与上面的类似，如果实现了其他 <code>*.Aware</code>接口，就调用相应的方法。</li>
<li>如果有和加载这个 Bean 的 Spring 容器相关的 <code>BeanPostProcessor</code> 对象，执行<code>postProcessBeforeInitialization()</code> 方法</li>
<li>如果Bean实现了<code>InitializingBean</code>接口，执行<code>afterPropertiesSet()</code>方法。</li>
<li>如果 Bean 在配置文件中的定义包含 init-method 属性，执行指定的方法。</li>
<li>如果有和加载这个 Bean的 Spring 容器相关的 <code>BeanPostProcessor</code> 对象，执行<code>postProcessAfterInitialization()</code> 方法</li>
<li>当要销毁 Bean 的时候，如果 Bean 实现了 <code>DisposableBean</code> 接口，执行 <code>destroy()</code> 方法。</li>
<li>当要销毁 Bean 的时候，如果 Bean 在配置文件中的定义包含 destroy-method 属性，执行指定的方法。</li>
</ul>
<h3 id="SpringMVC"><a href="#SpringMVC" class="headerlink" title="SpringMVC"></a>SpringMVC</h3><p>MVC 是一种设计模式,Spring MVC 是一款很优秀的 MVC 框架。Spring MVC 可以帮助我们进行更简洁的Web层的开发，并且它天生与 Spring 框架集成。Spring MVC 下我们一般把后端项目分为 Service层（处理业务）、Dao层（数据库操作）、Entity层（实体类）、Controller层(控制层，返回数据给前台页面)。</p>
<p><img src="http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-11/60679444.jpg" alt="springmvc"></p>
<h4 id="工作原理"><a href="#工作原理" class="headerlink" title="工作原理"></a>工作原理</h4><p><img src="http://my-blog-to-use.oss-cn-beijing.aliyuncs.com/18-10-11/49790288.jpg" alt="springmvc工作原理"></p>
<p><strong>流程说明（重要）：</strong></p>
<ol>
<li>客户端（浏览器）发送请求，直接请求到 <code>DispatcherServlet</code>。</li>
<li><code>DispatcherServlet</code> 根据请求信息调用 <code>HandlerMapping</code>，解析请求对应的 <code>Handler</code>。</li>
<li>解析到对应的 <code>Handler</code>（也就是我们平常说的 <code>Controller</code> 控制器）后，开始由 <code>HandlerAdapter</code> 适配器处理。</li>
<li><code>HandlerAdapter</code> 会根据 <code>Handler</code>来调用真正的处理器开处理请求，并处理相应的业务逻辑。</li>
<li>处理器处理完业务后，会返回一个 <code>ModelAndView</code> 对象，<code>Model</code> 是返回的数据对象，<code>View</code> 是个逻辑上的 <code>View</code>。</li>
<li><code>ViewResolver</code> 会根据逻辑 <code>View</code> 查找实际的 <code>View</code>。</li>
<li><code>DispaterServlet</code> 把返回的 <code>Model</code> 传给 <code>View</code>（视图渲染）。</li>
<li>把 <code>View</code> 返回给请求者（浏览器）</li>
</ol>
<h3 id="Spring都用到了哪些设计模式"><a href="#Spring都用到了哪些设计模式" class="headerlink" title="Spring都用到了哪些设计模式"></a>Spring都用到了哪些设计模式</h3><ul>
<li><strong>工厂设计模式</strong> : Spring使用工厂模式通过 <code>BeanFactory</code>、<code>ApplicationContext</code> 创建 bean 对象。</li>
<li><strong>代理设计模式</strong> : Spring AOP 功能的实现。</li>
<li><strong>单例设计模式</strong> : Spring 中的 Bean 默认都是单例的。</li>
<li><strong>模板方法模式</strong> : Spring 中 <code>jdbcTemplate</code>、<code>hibernateTemplate</code> 等以 Template 结尾的对数据库操作的类，它们就使用到了模板模式。</li>
<li><strong>包装器设计模式</strong> : 我们的项目需要连接多个数据库，而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。</li>
<li><strong>观察者模式:</strong> Spring 事件驱动模型就是观察者模式很经典的一个应用。</li>
<li><strong>适配器模式</strong> :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配<code>Controller</code>。</li>
<li>……</li>
</ul>
<h3 id="Spring事务"><a href="#Spring事务" class="headerlink" title="Spring事务"></a>Spring事务</h3><h4 id="管理事物有几种"><a href="#管理事物有几种" class="headerlink" title="管理事物有几种"></a>管理事物有几种</h4><ul>
<li>编程式事务，在代码中硬编码。</li>
<li>声明式事务，在配置文件中配置</li>
</ul>
<p><strong>声明式事务又分为两种</strong>：</p>
<ol>
<li>基于XML的声明式事务</li>
<li>基于注解的声明式事务</li>
</ol>
<h4 id="隔离级别"><a href="#隔离级别" class="headerlink" title="隔离级别"></a>隔离级别</h4><p><strong>隔离级别就跟mysql几乎差不多</strong></p>
<h4 id="源码分析"><a href="#源码分析" class="headerlink" title="源码分析"></a>源码分析</h4><ol>
<li>开启@EnableTransactionManagement</li>
<li>利用TransactionManagementConfigurationSelector给容器中会导入组件<ol>
<li>AutoProxyRegistrar</li>
<li>ProxyTransactionManagementConfiguration</li>
</ol>
</li>
<li>AutoProxyRegistrar：<ol>
<li>给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件；</li>
<li>利用后置处理器机制在对象创建以后，包装对象，返回一个代理对象（增强器），代理对象执行方法利用拦截器链进行调用；</li>
</ol>
</li>
<li>ProxyTransactionManagementConfiguration 做了什么？<ol>
<li>给容器中注册事务增强器；<ol>
<li>事务增强器要用事务注解的信息，AnnotationTransactionAttributeSource解析事务注解</li>
<li>事务拦截器：<ol>
<li>TransactionInterceptor；保存了事务属性信息，事务管理器；</li>
<li>他是一个 MethodInterceptor；在目标方法执行的时候；<ol>
<li>先获取事务相关的属性</li>
<li>再获取PlatformTransactionManager，如果事先没有添加指定任何transactionmanger，最终会从容器中按照类型获取一个PlatformTransactionManager；</li>
<li>执行目标方法<ol>
<li>如果异常，获取到事务管理器，利用事务管理回滚操作；</li>
<li>如果正常，利用事务管理器，提交事务</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
</ol>
<h3 id="Springboot启动流程"><a href="#Springboot启动流程" class="headerlink" title="Springboot启动流程"></a>Springboot启动流程</h3><h4 id="SpringApplication实例"><a href="#SpringApplication实例" class="headerlink" title="SpringApplication实例"></a>SpringApplication实例</h4><pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> <span class="token function">SpringApplication</span><span class="token punctuation">(</span>ResourceLoader resourceLoader<span class="token punctuation">,</span> Class<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> primarySources<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>sources <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">LinkedHashSet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 1. </span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>bannerMode <span class="token operator">=</span> Mode<span class="token punctuation">.</span>CONSOLE<span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>logStartupInfo <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>addCommandLineProperties <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>headless <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>registerShutdownHook <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>additionalProfiles <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HashSet</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>resourceLoader <span class="token operator">=</span> resourceLoader<span class="token punctuation">;</span>
        Assert<span class="token punctuation">.</span><span class="token function">notNull</span><span class="token punctuation">(</span>primarySources<span class="token punctuation">,</span> <span class="token string">"PrimarySources must not be null"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>primarySources <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">LinkedHashSet</span><span class="token punctuation">(</span>Arrays<span class="token punctuation">.</span><span class="token function">asList</span><span class="token punctuation">(</span>primarySources<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>webApplicationType <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">deduceWebApplicationType</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setInitializers</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getSpringFactoriesInstances</span><span class="token punctuation">(</span>ApplicationContextInitializer<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 3. </span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setListeners</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getSpringFactoriesInstances</span><span class="token punctuation">(</span>ApplicationListener<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 4.</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span>mainApplicationClass <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">deduceMainApplicationClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 5.</span>
    <span class="token punctuation">}</span></code></pre>
<ul>
<li><code>com.example.helloworld.HelloworldApplication</code>放入到Set的集合中</li>
<li>判断是否为Web环境：存在（javax.servlet.Servlet &amp;&amp; org.springframework.web.context.ConfigurableWebApplicationContext ）类</li>
<li>创建并初始化ApplicationInitializer列表 （spring.factories）</li>
<li>创建并初始化ApplicationListener列表 （spring.factories）</li>
<li>初始化主类mainApplicatioClass (DemoApplication)</li>
<li><strong>总结：上面就是SpringApplication初始化的代码，new SpringApplication()没做啥事情 ，主要加载了META-INF/spring.factories 下面定义的事件监听器接口实现类</strong></li>
</ul>
<h4 id="ConfigurableApplicationContext的run方法"><a href="#ConfigurableApplicationContext的run方法" class="headerlink" title="ConfigurableApplicationContext的run方法"></a>ConfigurableApplicationContext的run方法</h4><pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> ConfigurableApplicationContext <span class="token function">run</span><span class="token punctuation">(</span>String<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        StopWatch stopWatch <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StopWatch</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 1. 创建计时器StopWatch</span>
        stopWatch<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        ConfigurableApplicationContext context <span class="token operator">=</span> null<span class="token punctuation">;</span>
        Collection<span class="token operator">&lt;</span>SpringBootExceptionReporter<span class="token operator">></span> exceptionReporters <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ArrayList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">configureHeadlessProperty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        SpringApplicationRunListeners listeners <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getRunListeners</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 2. 获取SpringApplicationRunListeners并启动</span>
        listeners<span class="token punctuation">.</span><span class="token function">starting</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// </span>

        Collection exceptionReporters<span class="token punctuation">;</span>
        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            ApplicationArguments applicationArguments <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DefaultApplicationArguments</span><span class="token punctuation">(</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 创建ApplicationArguments</span>
            ConfigurableEnvironment environment <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">prepareEnvironment</span><span class="token punctuation">(</span>listeners<span class="token punctuation">,</span> applicationArguments<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 创建并初始化ConfigurableEnvironment</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">configureIgnoreBeanInfo</span><span class="token punctuation">(</span>environment<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// </span>
            Banner printedBanner <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">printBanner</span><span class="token punctuation">(</span>environment<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">//  打印Banner</span>
            context <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">createApplicationContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 创建ConfigurableApplicationContext</span>
            exceptionReporters <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getSpringFactoriesInstances</span><span class="token punctuation">(</span>SpringBootExceptionReporter<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token keyword">new</span> <span class="token class-name">Class</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">{</span>ConfigurableApplicationContext<span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">}</span><span class="token punctuation">,</span> context<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">prepareContext</span><span class="token punctuation">(</span>context<span class="token punctuation">,</span> environment<span class="token punctuation">,</span> listeners<span class="token punctuation">,</span> applicationArguments<span class="token punctuation">,</span> printedBanner<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">// 准备ConfigurableApplicationContext</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">refreshContext</span><span class="token punctuation">(</span>context<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 刷新ConfigurableApplicationContext，这个refreshContext()加载了bean，还启动了内置web容器，需要细细的去看看</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">afterRefresh</span><span class="token punctuation">(</span>context<span class="token punctuation">,</span> applicationArguments<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment" spellcheck="true">// 容器刷新后动作，啥都没做</span>
            stopWatch<span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment" spellcheck="true">// 计时器停止计时</span>
            <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>logStartupInfo<span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">StartupInfoLogger</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>mainApplicationClass<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">logStarted</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getApplicationLog</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> stopWatch<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token punctuation">}</span>

            listeners<span class="token punctuation">.</span><span class="token function">started</span><span class="token punctuation">(</span>context<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">callRunners</span><span class="token punctuation">(</span>context<span class="token punctuation">,</span> applicationArguments<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Throwable</span> var10<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">handleRunFailure</span><span class="token punctuation">(</span>context<span class="token punctuation">,</span> var10<span class="token punctuation">,</span> exceptionReporters<span class="token punctuation">,</span> listeners<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalStateException</span><span class="token punctuation">(</span>var10<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">try</span> <span class="token punctuation">{</span>
            listeners<span class="token punctuation">.</span><span class="token function">running</span><span class="token punctuation">(</span>context<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">return</span> context<span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span><span class="token class-name">Throwable</span> var9<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">handleRunFailure</span><span class="token punctuation">(</span>context<span class="token punctuation">,</span> var9<span class="token punctuation">,</span> exceptionReporters<span class="token punctuation">,</span> <span class="token punctuation">(</span>SpringApplicationRunListeners<span class="token punctuation">)</span>null<span class="token punctuation">)</span><span class="token punctuation">;</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">IllegalStateException</span><span class="token punctuation">(</span>var9<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span></code></pre>
<ul>
<li>创建计时器StopWatch</li>
<li>获取SpringApplicationRunListeners并启动</li>
<li>创建ApplicationArguments</li>
<li>创建并初始化ConfigurableEnvironment</li>
<li>打印Banner</li>
<li>创建ConfigurableApplicationContext</li>
<li>准备ConfigurableApplicationContext</li>
<li>刷新ConfigurableApplicationContext，<strong>这个refreshContext()加载了bean，还启动了内置web容器，需要细细的去看看</strong></li>
<li>容器刷新后动作，啥都没做</li>
<li>计时器停止计时</li>
</ul>
<h4 id="refreshContext"><a href="#refreshContext" class="headerlink" title="refreshContext()"></a>refreshContext()</h4><p><strong>该源码中其实就是Spring源码的refresh()的源码</strong></p>
<ul>
<li><strong>不过这里的refresh()是在<code>AbstractApplicationContext</code>抽象类上</strong></li>
<li><strong>其他就不提了，关注点在onrefresh()方法上，但是个空方法，毕竟是抽象类，去找其子类继承的它</strong></li>
<li><strong>debug调试可以找到ServletWebServerApplicationContext</strong></li>
</ul>
<h4 id="ServletWebServerApplicationContext"><a href="#ServletWebServerApplicationContext" class="headerlink" title="ServletWebServerApplicationContext"></a>ServletWebServerApplicationContext</h4><p><img src="http://media.dreamcat.ink//20200203211202.png" alt=""></p>
<ul>
<li><code>onRefresh()</code>-&gt;<code>createWebServer()</code>-&gt;<code>getWebServerFactory()</code>，此时已经加载了个web容器</li>
<li>可以返回刚才的<code>createWebServer()</code>，然后看<code>factory.getWebServer</code></li>
</ul>
<pre class=" language-java"><code class="language-java"><span class="token keyword">public</span> WebServer <span class="token function">getWebServer</span><span class="token punctuation">(</span>ServletContextInitializer<span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> initializers<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment" spellcheck="true">//tomcat这位大哥出现了</span>
        Tomcat tomcat <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Tomcat</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        File baseDir <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>baseDirectory <span class="token operator">!=</span> null <span class="token operator">?</span> <span class="token keyword">this</span><span class="token punctuation">.</span>baseDirectory
                <span class="token operator">:</span> <span class="token function">createTempDir</span><span class="token punctuation">(</span><span class="token string">"tomcat"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        tomcat<span class="token punctuation">.</span><span class="token function">setBaseDir</span><span class="token punctuation">(</span>baseDir<span class="token punctuation">.</span><span class="token function">getAbsolutePath</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        Connector connector <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Connector</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>protocol<span class="token punctuation">)</span><span class="token punctuation">;</span>
        tomcat<span class="token punctuation">.</span><span class="token function">getService</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addConnector</span><span class="token punctuation">(</span>connector<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">customizeConnector</span><span class="token punctuation">(</span>connector<span class="token punctuation">)</span><span class="token punctuation">;</span>
        tomcat<span class="token punctuation">.</span><span class="token function">setConnector</span><span class="token punctuation">(</span>connector<span class="token punctuation">)</span><span class="token punctuation">;</span>
        tomcat<span class="token punctuation">.</span><span class="token function">getHost</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">setAutoDeploy</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token function">configureEngine</span><span class="token punctuation">(</span>tomcat<span class="token punctuation">.</span><span class="token function">getEngine</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">for</span> <span class="token punctuation">(</span>Connector additionalConnector <span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>additionalTomcatConnectors<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            tomcat<span class="token punctuation">.</span><span class="token function">getService</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">addConnector</span><span class="token punctuation">(</span>additionalConnector<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token function">prepareContext</span><span class="token punctuation">(</span>tomcat<span class="token punctuation">.</span><span class="token function">getHost</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> initializers<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token function">getTomcatWebServer</span><span class="token punctuation">(</span>tomcat<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span></code></pre>
<ul>
<li>内置的Tomcat就出现了</li>
<li><strong>总结：run() 方法主要调用了spring容器启动方法扫描配置，加载bean到spring容器中；启动的内置Web容器</strong></li>
</ul>
<h4 id="SpringBootApplication的注解"><a href="#SpringBootApplication的注解" class="headerlink" title="SpringBootApplication的注解"></a>SpringBootApplication的注解</h4><p><strong>主要是三个注解</strong></p>
<ul>
<li>@SpringBootConfiguration:允许在上下文中注册额外的bean或导入其他配置类。</li>
<li>@EnableAutoConfiguration:启用 SpringBoot 的自动配置机制</li>
<li>@ComponentScan: 扫描常用的注解</li>
</ul>

      
    </div>
    <div class="article-footer">
      <blockquote class="mt-2x">
  <ul class="post-copyright list-unstyled">
    
    <li class="post-copyright-link hidden-xs">
      <strong>本文链接：</strong>
      <a href="http://dreamcat.ink/2020/03/29/ge-ren-tu-xie-xi-lie-zong-jie-spring/" title="个人吐血系列-总结Spring" target="_blank" rel="external">http://dreamcat.ink/2020/03/29/ge-ren-tu-xie-xi-lie-zong-jie-spring/</a>
    </li>
    
    <li class="post-copyright-license">
      <strong>版权声明： </strong> 本博客所有文章除特别声明外，均采用 <a href="http://creativecommons.org/licenses/by/4.0/deed.zh" target="_blank" rel="external">CC BY 4.0 CN协议</a> 许可协议。转载请注明出处！
    </li>
  </ul>
</blockquote>


<div class="panel panel-default panel-badger">
  <div class="panel-body">
    <figure class="media">
      <div class="media-left">
        <a href="https://github.com/DreamCats" target="_blank" class="img-burn thumb-sm visible-lg">
          <img src="/images/avatar.jpg" class="img-rounded w-full" alt="">
        </a>
      </div>
      <div class="media-body">
        <h3 class="media-heading"><a href="https://github.com/DreamCats" target="_blank"><span class="text-dark">Dreamcat</span><small class="ml-1x">ドリームキャット</small></a></h3>
        <div>个人简介。</div>
      </div>
    </figure>
  </div>
</div>


    </div>
  </article>
  
    
  <section id="comments">
  	
      <div id="vcomments"></div>
    
  </section>


  
</div>

  <nav class="bar bar-footer clearfix" data-stick-bottom>
  <div class="bar-inner">
  
  <ul class="pager pull-left">
    
    <li class="prev">
      <a href="/2020/03/29/ge-ren-tu-xie-xi-lie-zong-jie-mybatis/" title="个人吐血系列-总结Mybatis"><i class="icon icon-angle-left" aria-hidden="true"></i><span>&nbsp;&nbsp;上一篇</span></a>
    </li>
    
    
    <li class="next">
      <a href="/2020/03/28/ge-ren-tu-xie-xi-lie-zong-jie-jvm/" title="个人吐血系列-总结JVM"><span>下一篇&nbsp;&nbsp;</span><i class="icon icon-angle-right" aria-hidden="true"></i></a>
    </li>
    
    
    <li class="toggle-toc">
      <a class="toggle-btn collapsed" data-toggle="collapse" href="#collapseToc" aria-expanded="false" title="文章目录" role="button">
        <span>[&nbsp;</span><span>文章目录</span>
        <i class="text-collapsed icon icon-anchor"></i>
        <i class="text-in icon icon-close"></i>
        <span>]</span>
      </a>
    </li>
    
  </ul>
  
  
  <!-- Button trigger modal -->
  <button type="button" class="btn btn-fancy btn-donate pop-onhover bg-gradient-warning" data-toggle="modal" data-target="#donateModal"><span>赏</span></button>
  <!-- <div class="wave-icon wave-icon-danger btn-donate" data-toggle="modal" data-target="#donateModal">
    <div class="wave-circle"><span class="icon"><i class="icon icon-bill"></i></span></div>
  </div> -->
  
  
  <div class="bar-right">
    
    <div class="share-component" data-sites="weibo,qq,wechat,facebook,twitter" data-mobile-sites="weibo,qq,qzone"></div>
    
  </div>
  </div>
</nav>
  
<!-- Modal -->
<div class="modal modal-center modal-small modal-xs-full fade" id="donateModal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content donate">
      <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
      <div class="modal-body">
        <div class="donate-box">
          <div class="donate-head">
            <p>感谢您的支持，我会继续努力的!</p>
          </div>
          <div class="tab-content">
            <div role="tabpanel" class="tab-pane fade active in" id="alipay">
              <div class="donate-payimg">
                <img src="/images/donate/alipayimg.png" alt="扫码支持" title="扫一扫" />
              </div>
              <p class="text-muted mv">扫码打赏，你说多少就多少</p>
              <p class="text-grey">打开支付宝扫一扫，即可进行扫码打赏哦</p>
            </div>
            <div role="tabpanel" class="tab-pane fade" id="wechatpay">
              <div class="donate-payimg">
                <img src="/images/donate/wechatpayimg.png" alt="扫码支持" title="扫一扫" />
              </div>
              <p class="text-muted mv">扫码打赏，你说多少就多少</p>
              <p class="text-grey">打开微信扫一扫，即可进行扫码打赏哦</p>
            </div>
          </div>
          <div class="donate-footer">
            <ul class="nav nav-tabs nav-justified" role="tablist">
              <li role="presentation" class="active">
                <a href="#alipay" id="alipay-tab" role="tab" data-toggle="tab" aria-controls="alipay" aria-expanded="true"><i class="icon icon-alipay"></i> 支付宝</a>
              </li>
              <li role="presentation" class="">
                <a href="#wechatpay" role="tab" id="wechatpay-tab" data-toggle="tab" aria-controls="wechatpay" aria-expanded="false"><i class="icon icon-wepay"></i> 微信支付</a>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>



</main>

  <footer class="footer" itemscope itemtype="http://schema.org/WPFooter">
	
	
    <ul class="social-links">
    	
        <li><a href="https://github.com/DreamCats" target="_blank" title="Github" data-toggle=tooltip data-placement=top><i class="icon icon-github"></i></a></li>
        
        <li><a href="https://github.com/DreamCats" target="_blank" title="Weibo" data-toggle=tooltip data-placement=top><i class="icon icon-weibo"></i></a></li>
        
        <li><a href="https://github.com/DreamCats" target="_blank" title="Twitter" data-toggle=tooltip data-placement=top><i class="icon icon-twitter"></i></a></li>
        
        <li><a href="https://github.com/DreamCats" target="_blank" title="Behance" data-toggle=tooltip data-placement=top><i class="icon icon-behance"></i></a></li>
        
        <li><a href="/atom.xml" target="_blank" title="Rss" data-toggle=tooltip data-placement=top><i class="icon icon-rss"></i></a></li>
        
    </ul>

    <div class="copyright">
    	
        <div class="publishby">
        	Theme by <a href="https://github.com/cofess" target="_blank"> cofess </a>base on <a href="https://github.com/cofess/hexo-theme-pure" target="_blank">pure</a>.
        </div>
    </div>
</footer>
  <script src="//cdn.jsdelivr.net/npm/jquery@1.12.4/dist/jquery.min.js"></script>
<script>
window.jQuery || document.write('<script src="js/jquery.min.js"><\/script>')
</script>

<script src="/js/plugin.min.js"></script>


<script src="/js/application.js"></script>


    <script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
            UNTITLED: '(未命名)',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>

<script src="/js/insight.js"></script>






   




   
    
  <script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/valine"></script>
  <script type="text/javascript">
  var GUEST = ['nick', 'mail', 'link'];
  var meta = 'nick,mail,link';
  meta = meta.split(',').filter(function(item) {
    return GUEST.indexOf(item) > -1;
  });
  new Valine({
    el: '#vcomments',
    verify: false,
    notify: false,
    appId: '',
    appKey: '',
    placeholder: 'Just go go',
    avatar: 'mm',
    meta: meta,
    pageSize: '10' || 10,
    visitor: false
  });
  </script>

     







</body>
</html>